package com.zhuoyue.biz.core.command.cmd.common.fbf;

import com.zhuoyue.biz.core.api.domain.DeviceAndGatewayDO;
import com.zhuoyue.biz.core.api.dto.req.ControlReq;
import com.zhuoyue.biz.core.command.cmd.common.faa.base.ControlCmd;
import com.zhuoyue.common.constant.ControlType;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import com.zhuoyue.common.utils.AesUtils;
import com.zhuoyue.common.utils.AsciiUtil;

import com.zhuoyue.common.utils.Time;
import com.zhuoyue.common.xml.XmlParseUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author wjming
 * @ClassName: FingerprintLock_0FBF0202
 * @Description: zigbee指纹锁
 * @Date 2021-07-14 20:20
 */
@Component
public class FingerprintLock0Fbf0202 extends ControlCmd {
    private static String controlCmd = "";
    /**
     * 密码
     */
    private static final String PSD = "psd";

    public static synchronized Map<String, String> control(DeviceAndGatewayDO deviceAndGatewayDO, ControlReq controlReq, List<String> list) {
        Map<String, String> cmdAndPsd = new HashMap<>(2);
        String password = "";
        if (controlReq.getActions() != null && controlReq.getActions().get(PSD) != null) {
            //解密获取密码
            password = AesUtils.decrypt(controlReq.getActions().get(PSD) + "");
        } else {
            password = RandomStringUtils.randomNumeric(6);
//            password = "123123";
        }

        //获取秘钥
        String psdKey = new XmlParseUtil().getPsdKey(list);
        //进行加密
        List<Integer> encrypt = FingerprintRemotePsdDeal.encrypt(intToStringList(password), Integer.parseInt(psdKey, 16));
        String psdByteToString = listIntToString(encrypt);

        switch (controlReq.getControlType()) {
            //远程开启
            case ControlType.REMOTE_TURN_ON_REQUEST:
                //整理数据
                controlCmd = ControlCmd.myControlCmd(deviceAndGatewayDO, prdOpenTheDoor(psdByteToString), "03FA08", "");
                break;
            //设置一次性密码
            case ControlType.SET_OTP:
                controlCmd = ControlCmd.myControlCmd(deviceAndGatewayDO, prdOpenTheDoorTfd(psdByteToString), "03FA06", "");
                cmdAndPsd.put("psd", password);
                cmdAndPsd.put("type", "once");
                break;
            //一段时间内多次
            case ControlType.SET_PASSWORD_APERIOD_OF_TIME_CAN_USE:
                controlCmd = ControlCmd.myControlCmd(deviceAndGatewayDO, prdOpenTheDoorApot(psdByteToString, controlReq.getActions().get("startTime"), controlReq.getActions().get("endTime")), "03FA06", "");
                cmdAndPsd.put("psd", password);
                cmdAndPsd.put("type", "many_times");
                break;
            //取消时效性密码
            case ControlType.CANCEL_TIME_EFFECTIVE_PASSWORD:
                //进行加密
                encrypt = FingerprintRemotePsdDeal.encrypt(intToStringList("FFFFFF"), Integer.parseInt(psdKey, 16));
                psdByteToString = listIntToString(encrypt);
                controlCmd = ControlCmd.myControlCmd(deviceAndGatewayDO, prdOpenTheDoorApot(psdByteToString, Time.toLongMilli(LocalDateTime.now()) + 2000, Time.toLongMilli(LocalDateTime.now()) + 3000), "03FA06", "");
                cmdAndPsd.put("cancel", "cancel");
                cmdAndPsd.put("type", "many_times");
                break;
            //取消一次性密码
            case ControlType.CANCEL_ONE_TIME_PASSWORD:
                encrypt = FingerprintRemotePsdDeal.encrypt(intToStringList("FFFFFF"), Integer.parseInt(psdKey, 16));
                psdByteToString = listIntToString(encrypt);
                controlCmd = ControlCmd.myControlCmd(deviceAndGatewayDO, prdOpenTheDoorTfd(psdByteToString), "03FA06", "00");
                cmdAndPsd.put("cancel", "cancel");
                cmdAndPsd.put("type", "once");
                break;
            default:
                break;
        }
        cmdAndPsd.put("cmd", controlCmd);
        return cmdAndPsd;
    }

    /**
     * @Description:转16进制Ascii码
     * @param: password
     * @return: java.util.List<java.lang.Integer>
     * @author:wjming
     * @Date:2021/2/2 12:26
     */
    private static List<Integer> intToStringList(String password) {
        int two = 2;
        List<Integer> list = new ArrayList<>(6);
        //先转成As
        String passwordStr = AsciiUtil.stringToAscii(password);
        for (int i = 0; i < passwordStr.length(); i = i + two) {
            list.add(Integer.parseInt(StringUtils.substring(passwordStr, i, i + 2), 16));
        }
        return list;
    }

    /**
     * 主人开门
     *
     * @param password
     * @return
     */

    private static String prdOpenTheDoor(String password) {
        StringBuilder psd = new StringBuilder(password);
        do {
            psd.append("F");
        } while (psd.length() < 24);


        return "01" + psd.toString() + Long.toHexString(Time.toGetNowLongSecond()) + "00";
    }

    /**
     * 访客开门(一次)
     *
     * @param password
     * @return
     */

    private static String prdOpenTheDoorTfd(String password) {
        StringBuilder psd = new StringBuilder(password);
        do {
            psd.append("F");
        } while (psd.length() < 24);

        return "FFFFFFFFFFFFFFFFFFFFFFFF" + psd.toString() + "01" + Long.toHexString(Time.toGetNowLongSecond()) + "000000000000000000";
    }

    public static void main(String[] args) {
        System.out.println("args = " + prdOpenTheDoorTfd("11"));
    }

    /**
     * 访客开门(时间段), a period of time(一段时间)
     *
     * @param password
     * @return
     */

    private static String prdOpenTheDoorApot(String password, Object startTime, Object endTime) {
        StringBuilder psd = new StringBuilder(password);
        do {
            psd.append("F");
        } while (psd.length() < 24);

        if (startTime == null || Long.valueOf(startTime.toString()) < Time.toGetNowLongSecond()) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "开始时间错误");
        }
        if (startTime == null || Long.parseLong(endTime.toString()) < Time.toGetNowLongSecond()) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "结束时间错误");
        }
        if (Long.parseLong(endTime.toString()) < Long.valueOf(startTime.toString())) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "开始时间大于结束时间");
        }
        String startLong = Long.toHexString(Long.valueOf(startTime.toString()) / 1000);
        String endLong = Long.toHexString(Long.valueOf(endTime.toString()) / 1000);
        return "FFFFFFFFFFFFFFFFFFFFFFFF" + psd.toString() + "FF" + Long.toHexString(Time.toGetNowLongSecond()) + startLong + endLong + "00";
    }


    /**
     * List转String
     *
     * @param encrypt
     * @return
     */
    private static String listIntToString(List<Integer> encrypt) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < encrypt.size(); i++) {
            String s = Integer.toHexString(encrypt.get(i));
            stringBuilder.append(s.length() == 2 ? s : "0" + s);
        }
        return stringBuilder.toString();
    }

}
